package one.stand.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.jmp.base.dto.ChatGroupRemoveDto;
import com.jmp.base.dto.ChatGroupSaveDto;
import com.jmp.base.dto.ChatGroupSaveVo;
import com.jmp.feign.ChatFeign;
import com.jmp.livepush.LivePushClient;
import com.jmp.video.PullEventsVo;
import com.jmp.video.VideoClient;
import lombok.extern.slf4j.Slf4j;
import one.stand.advice.ResultEnum;
import one.stand.event.LiveRoomOpenEvent;
import one.stand.mapper.LiveRoomGoodsMapperExt;
import one.stand.mapper.LiveRoomMapperExt;
import one.stand.mapper.LiveUserMapperExt;
import one.stand.model.*;
import one.stand.service.BusinessCardBaseService;
import one.stand.service.LiveService;
import one.stand.service.user.UserAdminService;
import one.stand.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class LiveServiceImpl implements LiveService {

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private ChatFeign chatFeign;

    @Autowired
    private UserAdminService userAdminService;
    @Autowired
    private BusinessCardBaseService businessCardBaseService;

    @Autowired
    private LiveUserMapperExt liveUserMapperExt;
    @Autowired
    private LiveRoomMapperExt liveRoomMapperExt;
    @Autowired
    private LiveRoomGoodsMapperExt liveRoomGoodsMapperExt;
    @Autowired
    private LivePushClient livePushClient;
    @Autowired
    private VideoClient videoClient;

    @Override
    @Transactional
    public void save(Integer cardId, LiveRoom liveRoom, List<Integer> goodsIds) {
        LiveUser liveUser = liveUserMapperExt.selectByCardId(cardId);
        if (Objects.isNull(liveUser)) {
            liveUser = new LiveUser();
            liveUser.setCardId(cardId);
            liveUserMapperExt.insertSelective(liveUser);
        } else {
            AssertUtil.isNull(liveUser.getRoomId(), ResultEnum.PARAM_CHECK, "已存在直播");
        }

        liveRoom.setVideoType(VIDEO_TYPE_LIVE);
        liveRoom.setLiveUserId(liveUser.getId());
        liveRoom.setScreenshotUrl(liveRoom.getPhoto());//默认创建图
        liveRoomMapperExt.insertSelective(liveRoom);

        LiveRoomGoods liveRoomGoods;
        for (Integer goodsId : goodsIds) {
            if (Objects.isNull(goodsId)) continue;

            liveRoomGoods = new LiveRoomGoods();
            liveRoomGoods.setRoomId(liveRoom.getId());
            liveRoomGoods.setGoodsId(goodsId);
            liveRoomGoods.setStatus(GOODS_DOWN);
            liveRoomGoodsMapperExt.insertSelective(liveRoomGoods);
        }

        LiveUser liveUserUpdate = new LiveUser();
        liveUserUpdate.setId(liveUser.getId());
        liveUserUpdate.setRoomId(liveRoom.getId());
        liveUserMapperExt.updateByPrimaryKeySelective(liveUserUpdate);

        if (liveRoom.getPreFlag() == 0) {//无预告时，立即开播
            open(liveRoom.getId());
        } else {
            liveRoomMapperExt.updateOn(liveRoom.getId());
        }
    }

    @Override
    public void saveVideo(Integer cardId, String fileId, String name, String coverUrl, String videoUrl, Integer videoDuration) {
        LiveUser liveUser = liveUserMapperExt.selectByCardId(cardId);
        if (Objects.isNull(liveUser)) {
            liveUser = new LiveUser();
            liveUser.setCardId(cardId);
            liveUserMapperExt.insertSelective(liveUser);
        }

        LiveRoom liveRoom = new LiveRoom();
        liveRoom.setLiveUserId(liveUser.getId());
        liveRoom.setVideoType(VIDEO_TYPE_VIDEO);
        liveRoom.setName(StringUtils.defaultIfBlank(name, "短视频"));
        liveRoom.setPhoto(coverUrl);
        liveRoom.setPreFlag(0);//预告状态: 0无 1预告
        liveRoom.setLiveStatus(LIVE_STATUS_OFF);
        liveRoom.setFileId(fileId);
        liveRoom.setReplayUrl(videoUrl);
        liveRoom.setVideoDuration(ObjectUtil.defaultIfNull(videoDuration, 0));
        liveRoom.setScreenshotUrl(coverUrl);
        liveRoom.setIsDel(0);
        liveRoom.setIsOn(1);
        liveRoom.setCreateTime(new Date());
        liveRoomMapperExt.insertSelective(liveRoom);
    }

    @Override
    @Async("asyncServiceExecutor")
    public void saveVideoAsync() {
        PullEventsVo pullEventsVo = videoClient.pullEvents();

        int fileAddNum = 0;
        if (Objects.nonNull(pullEventsVo)) {
            List<String> eventHandles = Lists.newArrayList();
            for (PullEventsVo.File file : pullEventsVo.getFileUploadEvents()) {
                try {
                    Integer userId = Integer.valueOf(file.getSourceContext());
                    BusinessCard card = businessCardBaseService.getByUserId(userId);
                    saveVideo(card.getCardId(), file.getFileId(), file.getName(), file.getCoverUrl(), file.getMediaUrl(), Math.round(file.getVideoDuration()));

                    eventHandles.add(file.getEventHandle());

                    fileAddNum++;
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (OneListUtil.isNotEmpty(eventHandles)) {
                videoClient.confirmEvents(eventHandles);
            }
        }
        log.info("video save: {}", fileAddNum);
    }

    @Override
    @Transactional
    public void remove(Integer roomId) {

        LiveRoom liveRoom = liveRoomMapperExt.selectByPrimaryKey(roomId);
        LiveUser liveUser = liveUserMapperExt.selectByPrimaryKey(liveRoom.getLiveUserId());
        RequestContext.User optUser = RequestContextHolder.getRequestContext().getUser();
        AssertUtil.isTrue(liveUser.getCardId().equals(optUser.getCardId())
                        || userAdminService.get(optUser.getUserId()).isAdminUser()
                , ResultEnum.PARAM_CHECK, "只能删除自己的数据");

        //直播中时
        if (liveRoom.getVideoType() == VIDEO_TYPE_LIVE && liveRoom.getLiveStatus() == LIVE_STATUS_ON) {
            //禁断推流
            livePushClient.forbidLiveStream(String.valueOf(liveRoom.getId()));
            //关闭群组
            chatFeign.groupRemove(ChatGroupRemoveDto.builder().groupId(liveRoom.getGroupId()).build());
        }

        if (liveRoom.getVideoType() == VIDEO_TYPE_LIVE) {
            liveUserMapperExt.updateRoomId(roomId);
        }
        if (StringUtils.isNoneBlank(liveRoom.getFileId())) {
            videoClient.delete(liveRoom.getFileId());
        }

        liveRoom = new LiveRoom();
        liveRoom.setId(roomId);
        liveRoom.setIsDel(1);
        liveRoom.setUpdateTime(new Date());
        liveRoomMapperExt.updateByPrimaryKeySelective(liveRoom);
    }

    @Override
    @Transactional
    public void goodsAdd(Integer cardId, List<Integer> goodsIds) {
        LiveUser liveUser = liveUserMapperExt.selectByCardId(cardId);

        liveRoomGoodsMapperExt.deleteByRoomId(liveUser.getRoomId());

        LiveRoomGoods liveRoomGoods;
        for (Integer goodsId : goodsIds) {
            liveRoomGoods = new LiveRoomGoods();
            liveRoomGoods.setRoomId(liveUser.getRoomId());
            liveRoomGoods.setGoodsId(goodsId);
            liveRoomGoods.setStatus(GOODS_DOWN);
            liveRoomGoodsMapperExt.insertSelective(liveRoomGoods);
        }
    }

    @Override
    @Transactional
    public void goodsUpdate(Integer roomGoodsId, Integer status) {
        LiveRoomGoods liveRoomGoods = new LiveRoomGoods();
        liveRoomGoods.setId(roomGoodsId);
        liveRoomGoods.setStatus(status);
        liveRoomGoodsMapperExt.updateByPrimaryKeySelective(liveRoomGoods);
    }

    @Override
    @Transactional
    public void updateBack(Integer roomId, String fileId, String replayUrl, String screenshotUrl, Integer viewerNum, String viewerPhotos) {
        LiveRoom liveRoom = new LiveRoom();
        liveRoom.setId(roomId);
        liveRoom.setFileId(fileId);
        liveRoom.setReplayUrl(replayUrl);
        liveRoom.setScreenshotUrl(screenshotUrl);
        liveRoom.setViewerNum(viewerNum);
        liveRoom.setViewerPhotos(viewerPhotos);
        liveRoom.setUpdateTime(new Date());
        liveRoomMapperExt.updateByPrimaryKeySelective(liveRoom);

        if (StringUtils.isNoneBlank(replayUrl)) {
            liveRoomMapperExt.updateOn(liveRoom.getId());
        }
    }

    @Override
    @Transactional
    public LiveRoom open(Integer roomId) {

        LiveRoom liveRoom = liveRoomMapperExt.selectByPrimaryKey(roomId);

        if (LiveService.LIVE_STATUS_NO == liveRoom.getLiveStatus()) {//第一次开播

            // IM 创建聊天室
            ResultModel<ChatGroupSaveVo> saveVoResultModel = chatFeign.groupSave(ChatGroupSaveDto.builder().name(String.valueOf(liveRoom.getId())).build());
            AssertUtil.isTrue(saveVoResultModel);
            // 推拉流
            String streamName = String.valueOf(liveRoom.getId());
            long txTime = DateUtil.getDate(new Date(), Calendar.DAY_OF_MONTH, 7).getTime() / 1000;

            LiveRoom liveRoomUpdate = new LiveRoom();
            liveRoomUpdate.setId(liveRoom.getId());
            liveRoomUpdate.setGroupId(saveVoResultModel.getData().getGroupId());
            liveRoomUpdate.setPullUrl(livePushClient.getPullUrl(streamName));
            liveRoomUpdate.setPushUrl(livePushClient.getPushUrl(streamName, txTime));
            liveRoomUpdate.setLiveStatus(LIVE_STATUS_ON);
            liveRoomMapperExt.updateByPrimaryKeySelective(liveRoomUpdate);

            liveRoomMapperExt.updateOn(liveRoom.getId());

            //通知
            applicationContext.publishEvent(new LiveRoomOpenEvent(roomId));
        }

        return liveRoomMapperExt.selectByPrimaryKey(roomId);
    }

    @Override
    public void upVideo(Integer id, String title) {
        LiveRoom liveRoom = liveRoomMapperExt.selectByPrimaryKey(id);

        LiveRoom liveRoomUpdate = new LiveRoom();
        liveRoomUpdate.setId(id);
        liveRoomUpdate.setName(title);
        liveRoomMapperExt.updateByPrimaryKeySelective(liveRoomUpdate);
        liveRoomMapperExt.updateOn(id);
    }

    @Override
    @Transactional
    public void quit(Integer roomId) {
        liveUserMapperExt.updateRoomId(roomId);

        LiveRoom liveRoomSelect = liveRoomMapperExt.selectByPrimaryKey(roomId);

        LiveRoom liveRoom = new LiveRoom();
        liveRoom.setId(roomId);
        liveRoom.setLiveStatus(LIVE_STATUS_OFF);
        liveRoom.setUpdateTime(new Date());
        liveRoomMapperExt.updateByPrimaryKeySelective(liveRoom);

        //关闭群组
        chatFeign.groupRemove(ChatGroupRemoveDto.builder().groupId(liveRoomSelect.getGroupId()).build());

        if (StringUtils.isBlank(liveRoomSelect.getReplayUrl())) {//无回放时
            liveRoomMapperExt.updateDown(liveRoom.getId());
        }
    }

    @Override
    @Transactional
    public void end(Integer roomId, boolean end) {
        if (end) {
            LiveRoom liveRoom = new LiveRoom();
            liveRoom.setId(roomId);
            liveRoom.setEndTime(new Date());
            liveRoomMapperExt.updateByPrimaryKeySelective(liveRoom);
        } else {
            liveRoomMapperExt.updateEnd(roomId);
        }
    }
}
